@threadlabs/looma 0.28.20 → 0.28.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1732,144 +1732,11 @@ var TaskList = Node$1.create({
1732
1732
  }
1733
1733
  });
1734
1734
  //#endregion
1735
- //#region ../../node_modules/.pnpm/@tiptap+extension-task-item@2.27.2_@tiptap+core@2.27.2_@tiptap+pm@2.27.2__@tiptap+pm@2.27.2/node_modules/@tiptap/extension-task-item/dist/index.js
1736
- /**
1737
- * Matches a task item to a - [ ] on input.
1738
- */
1739
- var inputRegex$4 = /^\s*(\[([( |x])?\])\s$/;
1740
- /**
1741
- * This extension allows you to create task items.
1742
- * @see https://www.tiptap.dev/api/nodes/task-item
1743
- */
1744
- var TaskItem = Node$1.create({
1745
- name: "taskItem",
1746
- addOptions() {
1747
- return {
1748
- nested: false,
1749
- HTMLAttributes: {},
1750
- taskListTypeName: "taskList",
1751
- a11y: void 0
1752
- };
1753
- },
1754
- content() {
1755
- return this.options.nested ? "paragraph block*" : "paragraph+";
1756
- },
1757
- defining: true,
1758
- addAttributes() {
1759
- return { checked: {
1760
- default: false,
1761
- keepOnSplit: false,
1762
- parseHTML: (element) => {
1763
- const dataChecked = element.getAttribute("data-checked");
1764
- return dataChecked === "" || dataChecked === "true";
1765
- },
1766
- renderHTML: (attributes) => ({ "data-checked": attributes.checked })
1767
- } };
1768
- },
1769
- parseHTML() {
1770
- return [{
1771
- tag: `li[data-type="${this.name}"]`,
1772
- priority: 51
1773
- }];
1774
- },
1775
- renderHTML({ node, HTMLAttributes }) {
1776
- return [
1777
- "li",
1778
- mergeAttributes(this.options.HTMLAttributes, HTMLAttributes, { "data-type": this.name }),
1779
- [
1780
- "label",
1781
- ["input", {
1782
- type: "checkbox",
1783
- checked: node.attrs.checked ? "checked" : null
1784
- }],
1785
- ["span"]
1786
- ],
1787
- ["div", 0]
1788
- ];
1789
- },
1790
- addKeyboardShortcuts() {
1791
- const shortcuts = {
1792
- Enter: () => this.editor.commands.splitListItem(this.name),
1793
- "Shift-Tab": () => this.editor.commands.liftListItem(this.name)
1794
- };
1795
- if (!this.options.nested) return shortcuts;
1796
- return {
1797
- ...shortcuts,
1798
- Tab: () => this.editor.commands.sinkListItem(this.name)
1799
- };
1800
- },
1801
- addNodeView() {
1802
- return ({ node, HTMLAttributes, getPos, editor }) => {
1803
- const listItem = document.createElement("li");
1804
- const checkboxWrapper = document.createElement("label");
1805
- const checkboxStyler = document.createElement("span");
1806
- const checkbox = document.createElement("input");
1807
- const content = document.createElement("div");
1808
- const updateA11Y = () => {
1809
- var _a, _b;
1810
- checkbox.ariaLabel = ((_b = (_a = this.options.a11y) === null || _a === void 0 ? void 0 : _a.checkboxLabel) === null || _b === void 0 ? void 0 : _b.call(_a, node, checkbox.checked)) || `Task item checkbox for ${node.textContent || "empty task item"}`;
1811
- };
1812
- updateA11Y();
1813
- checkboxWrapper.contentEditable = "false";
1814
- checkbox.type = "checkbox";
1815
- checkbox.addEventListener("mousedown", (event) => event.preventDefault());
1816
- checkbox.addEventListener("change", (event) => {
1817
- if (!editor.isEditable && !this.options.onReadOnlyChecked) {
1818
- checkbox.checked = !checkbox.checked;
1819
- return;
1820
- }
1821
- const { checked } = event.target;
1822
- if (editor.isEditable && typeof getPos === "function") editor.chain().focus(void 0, { scrollIntoView: false }).command(({ tr }) => {
1823
- const position = getPos();
1824
- if (typeof position !== "number") return false;
1825
- const currentNode = tr.doc.nodeAt(position);
1826
- tr.setNodeMarkup(position, void 0, {
1827
- ...currentNode === null || currentNode === void 0 ? void 0 : currentNode.attrs,
1828
- checked
1829
- });
1830
- return true;
1831
- }).run();
1832
- if (!editor.isEditable && this.options.onReadOnlyChecked) {
1833
- if (!this.options.onReadOnlyChecked(node, checked)) checkbox.checked = !checkbox.checked;
1834
- }
1835
- });
1836
- Object.entries(this.options.HTMLAttributes).forEach(([key, value]) => {
1837
- listItem.setAttribute(key, value);
1838
- });
1839
- listItem.dataset.checked = node.attrs.checked;
1840
- checkbox.checked = node.attrs.checked;
1841
- checkboxWrapper.append(checkbox, checkboxStyler);
1842
- listItem.append(checkboxWrapper, content);
1843
- Object.entries(HTMLAttributes).forEach(([key, value]) => {
1844
- listItem.setAttribute(key, value);
1845
- });
1846
- return {
1847
- dom: listItem,
1848
- contentDOM: content,
1849
- update: (updatedNode) => {
1850
- if (updatedNode.type !== this.type) return false;
1851
- listItem.dataset.checked = updatedNode.attrs.checked;
1852
- checkbox.checked = updatedNode.attrs.checked;
1853
- updateA11Y();
1854
- return true;
1855
- }
1856
- };
1857
- };
1858
- },
1859
- addInputRules() {
1860
- return [wrappingInputRule({
1861
- find: inputRegex$4,
1862
- type: this.type,
1863
- getAttributes: (match) => ({ checked: match[match.length - 1] === "x" })
1864
- })];
1865
- }
1866
- });
1867
- //#endregion
1868
1735
  //#region ../../node_modules/.pnpm/@tiptap+extension-blockquote@2.27.2_@tiptap+core@2.27.2_@tiptap+pm@2.27.2_/node_modules/@tiptap/extension-blockquote/dist/index.js
1869
1736
  /**
1870
1737
  * Matches a blockquote to a `>` as input.
1871
1738
  */
1872
- var inputRegex$3 = /^\s*>\s$/;
1739
+ var inputRegex$4 = /^\s*>\s$/;
1873
1740
  /**
1874
1741
  * This extension allows you to create blockquotes.
1875
1742
  * @see https://tiptap.dev/api/nodes/blockquote
@@ -1910,7 +1777,7 @@ var Blockquote = Node$1.create({
1910
1777
  },
1911
1778
  addInputRules() {
1912
1779
  return [wrappingInputRule({
1913
- find: inputRegex$3,
1780
+ find: inputRegex$4,
1914
1781
  type: this.type
1915
1782
  })];
1916
1783
  }
@@ -3861,7 +3728,7 @@ var Link = Mark.create({
3861
3728
  /**
3862
3729
  * Matches an image to a ![image](src "title") on input.
3863
3730
  */
3864
- var inputRegex$2 = /(?:^|\s)(!\[(.+|:?)]\((\S+)(?:(?:\s+)["'](\S+)["'])?\))$/;
3731
+ var inputRegex$3 = /(?:^|\s)(!\[(.+|:?)]\((\S+)(?:(?:\s+)["'](\S+)["'])?\))$/;
3865
3732
  /**
3866
3733
  * This extension allows you to insert images.
3867
3734
  * @see https://www.tiptap.dev/api/nodes/image
@@ -3905,7 +3772,7 @@ var Image = Node$1.create({
3905
3772
  },
3906
3773
  addInputRules() {
3907
3774
  return [nodeInputRule({
3908
- find: inputRegex$2,
3775
+ find: inputRegex$3,
3909
3776
  type: this.type,
3910
3777
  getAttributes: (match) => {
3911
3778
  const [, , alt, src, title] = match;
@@ -3962,7 +3829,7 @@ var LoomaImage = Image.extend({ addAttributes() {
3962
3829
  /**
3963
3830
  * Matches a highlight to a ==highlight== on input.
3964
3831
  */
3965
- var inputRegex$1 = /(?:^|\s)(==(?!\s+==)((?:[^=]+))==(?!\s+==))$/;
3832
+ var inputRegex$2 = /(?:^|\s)(==(?!\s+==)((?:[^=]+))==(?!\s+==))$/;
3966
3833
  /**
3967
3834
  * Matches a highlight to a ==highlight== on paste.
3968
3835
  */
@@ -4021,7 +3888,7 @@ var Highlight = Mark.create({
4021
3888
  },
4022
3889
  addInputRules() {
4023
3890
  return [markInputRule({
4024
- find: inputRegex$1,
3891
+ find: inputRegex$2,
4025
3892
  type: this.type
4026
3893
  })];
4027
3894
  },
@@ -4244,7 +4111,7 @@ var Placeholder = Extension.create({
4244
4111
  * This ensures that any text between backticks is formatted as code,
4245
4112
  * regardless of the surrounding characters (exception being another backtick).
4246
4113
  */
4247
- var inputRegex = /(^|[^`])`([^`]+)`(?!`)/;
4114
+ var inputRegex$1 = /(^|[^`])`([^`]+)`(?!`)/;
4248
4115
  /**
4249
4116
  * Matches inline code while pasting.
4250
4117
  */
@@ -4289,7 +4156,7 @@ var Code = Mark.create({
4289
4156
  },
4290
4157
  addInputRules() {
4291
4158
  return [markInputRule({
4292
- find: inputRegex,
4159
+ find: inputRegex$1,
4293
4160
  type: this.type
4294
4161
  })];
4295
4162
  },
@@ -6431,6 +6298,196 @@ var LoomaBlockSelection = Extension.create({
6431
6298
  }
6432
6299
  });
6433
6300
  //#endregion
6301
+ //#region ../../node_modules/.pnpm/@tiptap+extension-task-item@2.27.2_@tiptap+core@2.27.2_@tiptap+pm@2.27.2__@tiptap+pm@2.27.2/node_modules/@tiptap/extension-task-item/dist/index.js
6302
+ /**
6303
+ * Matches a task item to a - [ ] on input.
6304
+ */
6305
+ var inputRegex = /^\s*(\[([( |x])?\])\s$/;
6306
+ /**
6307
+ * This extension allows you to create task items.
6308
+ * @see https://www.tiptap.dev/api/nodes/task-item
6309
+ */
6310
+ var TaskItem = Node$1.create({
6311
+ name: "taskItem",
6312
+ addOptions() {
6313
+ return {
6314
+ nested: false,
6315
+ HTMLAttributes: {},
6316
+ taskListTypeName: "taskList",
6317
+ a11y: void 0
6318
+ };
6319
+ },
6320
+ content() {
6321
+ return this.options.nested ? "paragraph block*" : "paragraph+";
6322
+ },
6323
+ defining: true,
6324
+ addAttributes() {
6325
+ return { checked: {
6326
+ default: false,
6327
+ keepOnSplit: false,
6328
+ parseHTML: (element) => {
6329
+ const dataChecked = element.getAttribute("data-checked");
6330
+ return dataChecked === "" || dataChecked === "true";
6331
+ },
6332
+ renderHTML: (attributes) => ({ "data-checked": attributes.checked })
6333
+ } };
6334
+ },
6335
+ parseHTML() {
6336
+ return [{
6337
+ tag: `li[data-type="${this.name}"]`,
6338
+ priority: 51
6339
+ }];
6340
+ },
6341
+ renderHTML({ node, HTMLAttributes }) {
6342
+ return [
6343
+ "li",
6344
+ mergeAttributes(this.options.HTMLAttributes, HTMLAttributes, { "data-type": this.name }),
6345
+ [
6346
+ "label",
6347
+ ["input", {
6348
+ type: "checkbox",
6349
+ checked: node.attrs.checked ? "checked" : null
6350
+ }],
6351
+ ["span"]
6352
+ ],
6353
+ ["div", 0]
6354
+ ];
6355
+ },
6356
+ addKeyboardShortcuts() {
6357
+ const shortcuts = {
6358
+ Enter: () => this.editor.commands.splitListItem(this.name),
6359
+ "Shift-Tab": () => this.editor.commands.liftListItem(this.name)
6360
+ };
6361
+ if (!this.options.nested) return shortcuts;
6362
+ return {
6363
+ ...shortcuts,
6364
+ Tab: () => this.editor.commands.sinkListItem(this.name)
6365
+ };
6366
+ },
6367
+ addNodeView() {
6368
+ return ({ node, HTMLAttributes, getPos, editor }) => {
6369
+ const listItem = document.createElement("li");
6370
+ const checkboxWrapper = document.createElement("label");
6371
+ const checkboxStyler = document.createElement("span");
6372
+ const checkbox = document.createElement("input");
6373
+ const content = document.createElement("div");
6374
+ const updateA11Y = () => {
6375
+ var _a, _b;
6376
+ checkbox.ariaLabel = ((_b = (_a = this.options.a11y) === null || _a === void 0 ? void 0 : _a.checkboxLabel) === null || _b === void 0 ? void 0 : _b.call(_a, node, checkbox.checked)) || `Task item checkbox for ${node.textContent || "empty task item"}`;
6377
+ };
6378
+ updateA11Y();
6379
+ checkboxWrapper.contentEditable = "false";
6380
+ checkbox.type = "checkbox";
6381
+ checkbox.addEventListener("mousedown", (event) => event.preventDefault());
6382
+ checkbox.addEventListener("change", (event) => {
6383
+ if (!editor.isEditable && !this.options.onReadOnlyChecked) {
6384
+ checkbox.checked = !checkbox.checked;
6385
+ return;
6386
+ }
6387
+ const { checked } = event.target;
6388
+ if (editor.isEditable && typeof getPos === "function") editor.chain().focus(void 0, { scrollIntoView: false }).command(({ tr }) => {
6389
+ const position = getPos();
6390
+ if (typeof position !== "number") return false;
6391
+ const currentNode = tr.doc.nodeAt(position);
6392
+ tr.setNodeMarkup(position, void 0, {
6393
+ ...currentNode === null || currentNode === void 0 ? void 0 : currentNode.attrs,
6394
+ checked
6395
+ });
6396
+ return true;
6397
+ }).run();
6398
+ if (!editor.isEditable && this.options.onReadOnlyChecked) {
6399
+ if (!this.options.onReadOnlyChecked(node, checked)) checkbox.checked = !checkbox.checked;
6400
+ }
6401
+ });
6402
+ Object.entries(this.options.HTMLAttributes).forEach(([key, value]) => {
6403
+ listItem.setAttribute(key, value);
6404
+ });
6405
+ listItem.dataset.checked = node.attrs.checked;
6406
+ checkbox.checked = node.attrs.checked;
6407
+ checkboxWrapper.append(checkbox, checkboxStyler);
6408
+ listItem.append(checkboxWrapper, content);
6409
+ Object.entries(HTMLAttributes).forEach(([key, value]) => {
6410
+ listItem.setAttribute(key, value);
6411
+ });
6412
+ return {
6413
+ dom: listItem,
6414
+ contentDOM: content,
6415
+ update: (updatedNode) => {
6416
+ if (updatedNode.type !== this.type) return false;
6417
+ listItem.dataset.checked = updatedNode.attrs.checked;
6418
+ checkbox.checked = updatedNode.attrs.checked;
6419
+ updateA11Y();
6420
+ return true;
6421
+ }
6422
+ };
6423
+ };
6424
+ },
6425
+ addInputRules() {
6426
+ return [wrappingInputRule({
6427
+ find: inputRegex,
6428
+ type: this.type,
6429
+ getAttributes: (match) => ({ checked: match[match.length - 1] === "x" })
6430
+ })];
6431
+ }
6432
+ });
6433
+ //#endregion
6434
+ //#region src/editor/extensions/task-item.ts
6435
+ var taskSequence = 0;
6436
+ /** A task item's accessible name: its text, or "Task" while it has none. */
6437
+ var taskName = (node) => node.textContent.trim() || "Task";
6438
+ /**
6439
+ * Tiptap's task item with each checkbox named by its item's text, so a screen reader announces
6440
+ * the task rather than an unnamed checkbox. In the editor the checkbox points at the item's own
6441
+ * content with `aria-labelledby`, so the name follows every edit; saved HTML has no element to point
6442
+ * at, so its checkbox carries the text as `aria-label`.
6443
+ */
6444
+ var LoomaTaskItem = TaskItem.extend({
6445
+ renderHTML({ node, HTMLAttributes }) {
6446
+ return [
6447
+ "li",
6448
+ mergeAttributes(this.options.HTMLAttributes, HTMLAttributes, { "data-type": this.name }),
6449
+ [
6450
+ "label",
6451
+ ["input", {
6452
+ type: "checkbox",
6453
+ checked: node.attrs.checked ? "checked" : null,
6454
+ "aria-label": taskName(node)
6455
+ }],
6456
+ ["span"]
6457
+ ],
6458
+ ["div", 0]
6459
+ ];
6460
+ },
6461
+ addNodeView() {
6462
+ const parent = this.parent();
6463
+ return (props) => {
6464
+ const view = parent(props);
6465
+ const checkbox = view.dom instanceof Element ? view.dom.querySelector("input[type=\"checkbox\"]") : null;
6466
+ const content = view.contentDOM;
6467
+ if (!checkbox || !(content instanceof HTMLElement)) return view;
6468
+ content.id ||= `looma-task-${++taskSequence}`;
6469
+ const name = (node) => {
6470
+ if (node.textContent.trim()) {
6471
+ checkbox.setAttribute("aria-labelledby", content.id);
6472
+ checkbox.removeAttribute("aria-label");
6473
+ } else {
6474
+ checkbox.removeAttribute("aria-labelledby");
6475
+ checkbox.setAttribute("aria-label", "Task");
6476
+ }
6477
+ };
6478
+ name(props.node);
6479
+ return {
6480
+ ...view,
6481
+ update: (...args) => {
6482
+ const kept = view.update?.(...args) ?? false;
6483
+ if (kept) name(args[0]);
6484
+ return kept;
6485
+ }
6486
+ };
6487
+ };
6488
+ }
6489
+ });
6490
+ //#endregion
6434
6491
  //#region src/editor/extensions/list-behavior.ts
6435
6492
  /**
6436
6493
  * Looma list behavior extension:
@@ -10900,7 +10957,7 @@ function getDefaultEditorExtensions(options = {}) {
10900
10957
  OrderedList,
10901
10958
  ListItem,
10902
10959
  TaskList,
10903
- TaskItem.configure({ nested: false }),
10960
+ LoomaTaskItem.configure({ nested: false }),
10904
10961
  Blockquote,
10905
10962
  calloutNodeView ? LoomaCallout.extend({ addNodeView: () => calloutNodeView }) : LoomaCallout,
10906
10963
  LoomaChip,
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Tiptap's task item with each checkbox named by its item's text, so a screen reader announces
3
+ * the task rather than an unnamed checkbox. In the editor the checkbox points at the item's own
4
+ * content with `aria-labelledby`, so the name follows every edit; saved HTML has no element to point
5
+ * at, so its checkbox carries the text as `aria-label`.
6
+ */
7
+ export declare const LoomaTaskItem: import("@tiptap/core").Node<import("@tiptap/extension-task-item").TaskItemOptions, any>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@threadlabs/looma",
3
- "version": "0.28.20",
3
+ "version": "0.28.21",
4
4
  "type": "module",
5
5
  "description": "Looma components as HTML, Vue, and plain DOM, with design tokens.",
6
6
  "license": "MIT",